package rw.input;

import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map.Entry;
import java.util.Set;

/**
 * 输入采集类
 *
 * @author RWdaze
 */
public class Input extends KeyAdapter {
    /**
     * 单例模式
     */
    private static Input instance;

    private Input() {

    }

    public static Input getInstance() {
        if (instance == null) {
            instance = new Input();
        }
        return instance;
    }

    /**
     * 每一帧需要执行一次的函数。
     * 这样输入采集类才能准确的计算出"按下","按住","松开"三个状态
     */
    public void synchronizedSign() {
        // 遍历按键列表
        Set<Entry<String, Keys>> entrySet = inputKeys.entrySet();
        for (Entry<String, Keys> keys : entrySet) {
            keys.getValue().isPush = !keys.getValue().lastIsHold && keys.getValue().isHold;
            keys.getValue().isRelease = keys.getValue().lastIsHold && !keys.getValue().isHold;
            keys.getValue().lastIsHold = keys.getValue().isHold;
        }
    }

    /**
     * 把想要监听的按键加入输入采集类中
     *
     * @param name     你给这个按键起的名字
     * @param keyEvent 按键的keyEvent
     */
    public void putKey(String name, int... keyEvent) {
        LinkedList<Integer> keys = new LinkedList<>();
        for (int k : keyEvent) {
            keys.add(k);
        }
        inputKeys.put(name, new Keys(keys));
    }

    /**
     * 查询相应名字的按键这一帧是否"按下"（注意不是"按住"）
     *
     * @param name 按键的名字
     * @return 是否按下
     */
    public boolean isPush(String name) {
        return inputKeys.get(name).isPush;
    }

    /**
     * 查询相应名字的按键在这一帧是否"按住"(注意不是"按下")
     *
     * @param name 相应按键的名字
     * @return 是否被按住
     */
    public boolean isHold(String name) {
        return inputKeys.get(name).isHold;
    }

    /**
     * 查询相应名字的按键在这一帧是否弹起
     *
     * @param name 按键的名字
     * @return 是否弹起
     */
    public boolean isReleased(String name) {
        return inputKeys.get(name).isRelease;
    }

    /**
     * 按键列表
     */
    private final HashMap<String, Keys> inputKeys = new HashMap<>();

    /**
     * 按键状态类
     */
    private static class Keys {
        /**
         * 这个按键所拥有的所有keyEvent
         */
        public LinkedList<Integer> keys;

        public boolean lastIsHold = false;

        public boolean isHold = false;

        public boolean isPush = false;

        public boolean isRelease = false;

        public Keys(LinkedList<Integer> keys) {
            this.keys = keys;
        }
    }

    /**
     * 监听按键是否按下
     *
     * @param e KeyEvent
     */
    @Override
    public void keyPressed(KeyEvent e) {
        Set<Entry<String, Keys>> entrySet = inputKeys.entrySet();
        for (Entry<String, Keys> keys : entrySet) {
            LinkedList<Integer> keys2 = keys.getValue().keys;
            for (Integer k : keys2) {
                int ik = k;
                if (e.getKeyCode() == ik) {
                    keys.getValue().isHold = true;
                    break;
                }
            }
        }
    }

    /**
     * 监听按键是否弹起
     *
     * @param e KeyEvent
     */
    @Override
    public void keyReleased(KeyEvent e) {
        Set<Entry<String, Keys>> entrySet = inputKeys.entrySet();
        for (Entry<String, Keys> keys : entrySet) {
            LinkedList<Integer> keys2 = keys.getValue().keys;
            for (Integer k : keys2) {
                int ik = k;
                if (e.getKeyCode() == ik) {
                    keys.getValue().isHold = false;
                    break;
                }
            }
        }
    }
}